package xyz.bali16.module.blog.controller;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.gitee.starblues.bootstrap.annotation.AutowiredType;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;

import net.coobird.thumbnailator.Thumbnails;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;


import org.springframework.web.multipart.MultipartFile;
import xyz.bali16.application.core.enums.ApiEnum;
import xyz.bali16.application.core.exception.BusinessException;
import xyz.bali16.application.core.model.Result;
import xyz.bali16.application.core.utils.AuthUtils;
import xyz.bali16.application.core.utils.TimeUtil;
import xyz.bali16.application.entity.User;
import xyz.bali16.application.service.UserService;
import xyz.bali16.module.blog.entity.Article;
import xyz.bali16.module.blog.entity.Category;
import xyz.bali16.module.blog.entity.Tag;
import xyz.bali16.module.blog.model.vo.blog.ArticleConditionVo;
import xyz.bali16.module.blog.service.ArticleService;
import xyz.bali16.module.blog.service.ArticleTagService;
import xyz.bali16.module.blog.service.CategoryService;
import xyz.bali16.module.blog.service.TagService;
import xyz.bali16.module.blog.service.impl.NetdiskArticleCallService;
import xyz.bali16.module.netdisk.controller.utils.NetdiskArticleCallObj;


import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.*;

import static xyz.bali16.application.core.model.Result.failure;
import static xyz.bali16.application.core.model.Result.success;

@RestController
@RequestMapping(BaseController.API + "blog/article")
@Slf4j
public class ArticleController extends BaseController {
    @Autowired
    private NetdiskArticleCallService netdiskArticleCallService;
    @Autowired
    private CategoryService categoryService;
    @Autowired
    private TagService tagService;
    @Autowired
    private ArticleService articleService;
    @Autowired
    private ArticleTagService articleTagService;

    @Autowired
    @AutowiredType(AutowiredType.Type.PLUGIN_MAIN)
    private UserService userService;

    @PostMapping(value = "/file/img/upload")
    @ResponseBody
    @ApiOperation("文章上传文件")
    //@PreAuthorize("@auth.permission('plugin:blog:file:upload:img')")
    public Result<String> imgUpload(MultipartFile fileBlob, HttpServletRequest request) {
        try {
            System.out.println("存储的绝对地址:" + new File("").getAbsolutePath());
            File tempFile = new File(fileBlob.getOriginalFilename());
            System.out.println(tempFile.getName());
            System.out.println(tempFile);
            tempFile.createNewFile();
            Thumbnails.of(fileBlob.getInputStream()).size(300, 170).keepAspectRatio(false).toFile(tempFile); //尺寸处理
            FileInputStream inputStream = new FileInputStream(tempFile);
            MultipartFile multipartFile = new MockMultipartFile(tempFile.getName(), inputStream);
            return netdiskArticleCallService.upload(multipartFile, request);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return failure();

    }

    @PostMapping(value = "/file/upload")
    @ResponseBody
    @ApiOperation("文章上传文件")
    //@PreAuthorize("@auth.permission('plugin:blog:file:upload')")
    //todo 这里需要一个默认图管理 KV类型的
    public Result<String> upload(MultipartFile fileBlob, HttpServletRequest request) {
        try {
            //MultipartFile 转 File
            System.out.println("存储的绝对地址:" + new File("").getAbsolutePath());
            File tempFile = new File(fileBlob.getOriginalFilename());
            System.out.println(tempFile.getName());
            System.out.println(tempFile);
            tempFile.createNewFile();
            Thumbnails.of(fileBlob.getInputStream()).size(300, 170).keepAspectRatio(false).toFile(tempFile); //尺寸处理
            //File 转 MultipartFile
            //FileItem fileItem = null;
            //fileItem = new DiskFileItem("mainFile", Files.probeContentType(tempFile.toPath()), false, tempFile.getName(), (int) tempFile.length(), tempFile.getParentFile());
            //InputStream input = new FileInputStream(tempFile);
            //try (OutputStream os = fileItem.getOutputStream()) {
            //    IOUtils.copy(input, os);
            //    // Or faster..
            //    // IOUtils.copy(new FileInputStream(file), fileItem.getOutputStream());
            //    MultipartFile multipartFile = new CommonsMultipartFile(fileItem);
            //    tempFile.delete();
            //    return netdiskArticleCallService.upload(multipartFile, request);
            //} catch (IOException e) {
            //    e.printStackTrace();
            //}
            FileInputStream inputStream = new FileInputStream(tempFile);
            MultipartFile multipartFile = new MockMultipartFile(tempFile.getName(), inputStream);
            return netdiskArticleCallService.upload(multipartFile, request);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return failure();

    }

    /**
     * 根据条件列出文章列表
     * 1. 列名排序
     * 2. [关键词/文章内容]模糊搜索
     * 3. 分页功能
     * * Update: 2.25,bali16
     * * 让后台文章支持搜索功能
     * category为newest与hotest
     *
     * @param current
     * @param size
     * @param searchText
     * @param sortName
     * @param sortOrder
     * @return
     */
    @GetMapping("/list")
    @ResponseBody
    @ApiOperation("文章列表数据")
    //@PreAuthorize("@auth.permission('plugin:blog:query')")
    public Result list(@RequestParam(value = "current", required = false, defaultValue = "1") Integer current,
                       @RequestParam(value = "size", required = false, defaultValue = "5") Integer size,
                       @RequestParam(value = "searchText", required = false) String searchText,
                       @RequestParam(value = "sortName", required = false) String sortName,
                       @RequestParam(value = "sortOrder", required = false) String sortOrder,
                       @RequestParam(value = "category", required = false) String category,
                       @RequestParam(value = "tag", required = false) String tag) {
        ArticleConditionVo articleConditionVo = new ArticleConditionVo().setKeywords(searchText).setSortName(sortName).setSortOrder(sortOrder);
        articleConditionVo.setCurrent(current);
        articleConditionVo.setSize(size);
        if (!StringUtils.isBlank(tag)) {
            Wrapper tagWrapper = Wrappers.<Tag>lambdaQuery().eq(Tag::getName, tag);
            Tag _tag = tagService.getOne(tagWrapper);
            if (_tag != null) {
                articleConditionVo.setTagId(_tag.getId());
            }
        }
        if (!StringUtils.isBlank(category)) {
            Wrapper categoryWrapper = Wrappers.<Category>lambdaQuery().eq(Category::getName, category);
            Category _category = categoryService.getOne(categoryWrapper);
            if (_category != null) {
                articleConditionVo.setCategoryId(_category.getId());
                articleConditionVo.setCategory(_category.getName());
            }
        }

        return Result.success(articleService.queryPage(articleConditionVo));
    }

    @GetMapping("/hotList")
    @ResponseBody
    @ApiOperation("返回Top5热量帖子")
    //@PreAuthorize("@auth.permission('plugin:blog:query')")
    public Result<List<Article>> hotList() {
        return Result.success(articleService.hotList(5));
    }

    @GetMapping("/randomList")
    @ResponseBody
    @ApiOperation("返回5个随机帖子")
    //@PreAuthorize("@auth.permission('plugin:blog:query')")
    public Result<List<Article>> randomList() {
        return Result.success(articleService.randomList(5));
    }

    @RequestMapping(value = "/file/download")
    @ResponseBody
    @ApiOperation("文章下载文件")
    //@PreAuthorize("@auth.permission('plugin:blog:download')")
    public void download(@RequestParam(value = "fileId") String fileId, HttpServletRequest
            request, HttpServletResponse response) {
        netdiskArticleCallService.download(fileId, request, response);
    }

    @RequestMapping(value = "/file/delete")
    @ResponseBody
    @ApiOperation("文章删除上传文件")
    //@PreAuthorize("@auth.permission('plugin:blog:file:delete')")
    public Result<Boolean> delete(@RequestParam(value = "fileId") String fileId) {
        return Result.success(netdiskArticleCallService.delete(fileId));
    }

    @GetMapping(value = "/file/list")
    @ApiOperation("查看文章附件")
    //@PreAuthorize("@auth.permission('plugin:blog:file:query')")
    public Result<List<?>> fileList(@RequestParam(value = "current", required = false, defaultValue = "1") Integer current,
                                    @RequestParam(value = "size", required = false, defaultValue = "20") Integer size) {
        List<?> files = netdiskArticleCallService.list(current, size).getList();
        return success(files);
    }

    @GetMapping("/{articleId}")
    @ApiOperation("查看博客文章")
    //@PreAuthorize("@auth.permission('plugin:blog:query')")
    public Result<Article> get(@PathVariable("articleId") String articleId) {
        try {
            Article article = articleService.getById(articleId);
            return success(ApiEnum.GET_SUCCESS, article);
        } catch (Exception e) {
            return failure(ApiEnum.GET_ERROR, "获取文章失败", e);
        }
    }
    //@GetMapping(value = "/file/list/{imgId}")
    //@ApiOperation("查看文章附件")
    ////@RequiresPermissions("blog:article:edit")
    //public String fileList(Model model,
    //                       @PathVariable("imgId") String imgId,
    //                       @RequestParam(value = "current", required = false, defaultValue = "1") Integer current,
    //                       @RequestParam(value = "size", required = false, defaultValue = "20") Integer size) {
    //    List<?> files = netdiskArticleCallService.list(current, size).getList();
    //    //model.addAttribute("files", files);
    //    //System.out.println("imgId:" + imgId);
    //    //model.addAttribute("imgId", imgId);
    //}

    /**
     * 修改文章页面
     *
     * @return
     */
    @GetMapping(value = "/edit")
    //@PreAuthorize("@auth.permission('plugin:blog:update')")
    public Result<Map<String, Object>> editArticle(@RequestParam(value = "id", required = false) Long id) {
        String username = AuthUtils.getCurrentUsername();
        User user = userService.getByUsername(username);
        //获取所有分类
        List<Category> categorys = new ArrayList<>();
        /**新建**/
        // 获取所有标签
        List<Tag> tags = new ArrayList<>();
        categorys = categoryService.list();
        tags = tagService.list();
        Article article = null;
        List<Tag> aTags = new ArrayList<>();
        boolean created = id != null;
        if (!created) {
            article = new Article();
            article.setStatus(1).setRecommended(0);
        } else if (created) {
            article = articleService.getById(id);
            if (article == null) {
                throw new BusinessException("没有此文章");
            }

            List<Long> tagIds = articleTagService.queryTagIdList(article.getId());
            Category aCategory = categoryService.getById(article.getCategoryId());
            categorys.removeAll(Collections.singleton(aCategory));
            if (CollectionUtil.isEmpty(tagIds)) {
                aTags = new ArrayList<>();
            } else {
                aTags = tagService.listByIds(tagIds);
            }
            article.setTags(aTags);
            article.setCategory(aCategory);
        }
        System.out.println("测试:");
        //区分选中与所有 避免重复
        tags.removeAll(aTags);

        System.out.println(tags.toString());
        System.out.println(categorys.toString());
        System.out.println(article.toString());
        Map<String, Object> retMap = new HashMap<>();
        retMap.put("tags", tags);
        retMap.put("categorys", categorys);
        retMap.put("article", article);
        return success(retMap);
    }


    @PostMapping("/save")
    @ResponseBody
    //@PreAuthorize("@auth.permission('plugin:blog:save')")
    public Result save(@RequestBody Article article) {
        System.out.println("article" + article);
        String username = AuthUtils.getCurrentUsername();
        User user = userService.getByUsername(username);
        if (article.getUserId() == null) {
            article.setUserId(user.getUserId());
        }

        if (article.getAuthor() == null) {
            article.setAuthor(user.getUsername());
        }

        if (article.getGmtCreated() == null) {
            article.setGmtCreated(TimeUtil.getNowTimeToSeconds());
        }

        //文章URL用来做archive用
        if (article.getUrl() == null) {
            article.setUrl("/" + article.getUrl());
        }

        article.setGmtUpdated(TimeUtil.getNowTimeToSeconds());
        articleService.saveOrUpdate(article);

        ArrayList<Long> tagIds = new ArrayList<>();

        if (article.getUploadTags() != null) {
            for (String tagName : article.getUploadTags()) {
                Tag tag = tagService.getOne(Wrappers.<Tag>lambdaQuery().eq(Tag::getName, tagName));
                // 创建不存在的Tag
                if (tag == null) {
                    Tag newTag = new Tag();
                    newTag.setUrl(tagName);
                    newTag.setName(tagName);
                    tagService.save(newTag);
                    tagIds.add(newTag.getId());
                } else {
                    tagIds.add(tag.getId());
                }

            }
        }
        article.setTagIds(tagIds);
        System.out.println("article.setTagIds" + tagIds);
        articleTagService.addArticleTag(article.getId(), article.getTagIds());
        return Result.success();
    }

    @PostMapping(value = "/updateStatus")
    //@PreAuthorize("@auth.permission('plugin:blog:update')")
    public Result<Boolean> updateStatus(@RequestBody Map<Object, String> map) {
        Long id = Long.valueOf(map.get("id"));
        Integer status = Integer.valueOf(map.get("status"));
        boolean state = articleService.updateStatus(id, status);
        return Result.success(state);
    }

    @PostMapping("/remove")
    //@PreAuthorize("@auth.permission('plugin:blog:delete')")
    public Result<Boolean> remove(@RequestBody Map<Object, String> map) {
        Long id = Long.valueOf(map.get("id"));
        boolean state = articleService.removeById(id);
        return Result.success(state);
    }

}





